package post

import (
	"context"
	"strings"

	"mall/common/enumx"
	"mall/common/modelx"
	"mall/common/resultx"
	"mall/service/blog/model"
	"mall/service/blog/rpc/internal/svc"
	"mall/service/blog/rpc/types/blog"

	"github.com/zeromicro/go-zero/core/logx"
)

type PostDetailLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewPostDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PostDetailLogic {
	return &PostDetailLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *PostDetailLogic) PostDetail(in *blog.PostDetailRequest) (*blog.PostDetailResponse, error) {
	if in.Preload == "" && in.EagerLoad == "" {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	logx.Infof("PostDetailRequest: %+v ", in)
	// Preload:\"blogMedia:altText,sourceUrl,mediaDetails;blogPostMeta:fullHead,title,metaDesc;blogPost:AuthorId,CommentCount,CommentStatus,Date,Id,Uri,Slug,Title;blogTerm:Name,Slug,Name,Slug\" EagerLoad:\"blogPost:blogTerm,blogPostDetail,blogMedia,blogPostMeta,blogTerm\" Filter:\"Slug,equalTo:code-review\"

	preloadMap, eagerLoadMap := modelx.GetPreloadMap(in.Preload, in.EagerLoad)
	// logx.Infof("preloadMap: %+v ", preloadMap)
	// preloadMap:
	// logx.Infof("eagerLoadMap: %+v ", eagerLoadMap)
	// eagerLoadMap:

	blogPostEntityName := model.RpcEntityNames.BlogPost
	_, hasEntitySettings := model.RpcEntityPreloadMap[blogPostEntityName] // BlogPost的关联字段
	if !hasEntitySettings {
		return &blog.PostDetailResponse{}, nil
	}

	blogPostRepositoryName := model.RepositoryNames.BlogPost
	columnMap, hasColumnMap := model.RepositoryPreloadMap[blogPostRepositoryName] // BlogPost的数据库字段
	if !hasColumnMap {
		return &blog.PostDetailResponse{}, nil
	}

	var selectCols []string
	if preloadFields, hasPreloadFields := preloadMap[blogPostEntityName]; hasPreloadFields {
		selectColMap := make(map[string]string)
		for _, field := range preloadFields {
			if _, exist := selectColMap[field]; !exist {
				if column, hasColumn := columnMap[field]; hasColumn {
					selectColMap[field] = column
				} else {
					selectColMap[field] = ""
				}
			}
		}
		for _, column := range selectColMap {
			if column != "" {
				selectCols = append(selectCols, column)
			}
		}
	}

	var post *model.BlogPost
	if in.Filter != "" {
		var filterMap map[string]map[string][]any
		filterMap = modelx.GetFilterMap(in.Filter, columnMap)
		// logx.Infof("filterMap: %+v ", filterMap)
		// filterMap:

		var asPreview string
		if in.AsPreview {
			asPreview = "1"
		}
		var pageSize int64 = 1
		postList, _, err := l.svcCtx.BlogPost.GetList(l.ctx, model.M{
			"asPreview": asPreview,
			"pageSize":  pageSize,
			"select":    strings.Join(selectCols, ","),
		}, -1, filterMap)
		if err != nil {
			return nil, err
		}
		if len(postList) == 0 {
			return &blog.PostDetailResponse{}, nil
		}

		post = postList[0]
	} else if in.Id > 0 {
		postSingle, err := l.svcCtx.BlogPost.FindOne(l.ctx, in.Id, selectCols)
		if err != nil {
			if err == model.ErrNotFound {
				return &blog.PostDetailResponse{}, nil
			}

			return nil, err
		}

		post = postSingle
	}

	if post == nil {
		return &blog.PostDetailResponse{}, nil
	}
	pid := post.ID

	var contentHtml string
	var media []*blog.BlogMedia
	var meta []*blog.BlogMeta
	subRpcEntitySettingMap := make(map[string]map[string]*model.ColumnSetting)
	if eagerLoadRpcEntities, hasEagerLoadRpcEntities := eagerLoadMap[blogPostEntityName]; hasEagerLoadRpcEntities {
		for _, entity := range eagerLoadRpcEntities {
			if rpcEntitySettingMap, hasRpcEntitySettingMap := model.RpcEntityPreloadMap[entity]; hasRpcEntitySettingMap {
				subRpcEntitySettingMap[entity] = rpcEntitySettingMap
			}
		}
	}

	blogPostDetailRpcEntityName := model.RpcEntityNames.BlogPostDetail
	blogPostDetailRepositoryName := model.RepositoryNames.BlogPostDetail
	if _, hasRpcEntitySettingMap := subRpcEntitySettingMap[blogPostDetailRpcEntityName]; hasRpcEntitySettingMap {
		preloadFields, hasPreloadFields := preloadMap[blogPostDetailRpcEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogPostDetailRepositoryName]
		if hasPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range preloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}

			detailFilterMap := make(map[string]map[string][]any)
			detailFilterMap[model.BlogPostDetailColumns.PostID] = map[string][]any{
				"equalTo": []any{pid},
			}
			var pageSize int64 = 1
			detailList, _, err := l.svcCtx.BlogPost.GetDetail(l.ctx, model.M{
				"pageSize": pageSize,
				"select":   strings.Join(subSelectCols, ","),
			}, -1, detailFilterMap)
			if err != nil {
				return nil, err
			}
			if len(detailList) > 0 {
				contentHtml = detailList[0].PostContent
			}
		}
	}

	blogMediaRpcEntityName := model.RpcEntityNames.BlogMedia
	blogMediaRepositoryName := model.RepositoryNames.BlogMedia
	if _, hasRpcEntitySettingMap := subRpcEntitySettingMap[blogMediaRpcEntityName]; hasRpcEntitySettingMap {
		preloadFields, hasPreloadFields := preloadMap[blogMediaRpcEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogMediaRepositoryName]
		if hasPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range preloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}
			mediaFilterMap := make(map[string]map[string][]any)
			mediaFilterMap[model.BlogAttachmentRelationshipColumns.ObjectID] = map[string][]any{
				"equalTo": []any{pid},
			}
			mediaFilterMap[model.BlogAttachmentRelationshipColumns.ObjectType] = map[string][]any{
				"equalTo": []any{enumx.PostTypePost},
			}
			mediaFilterMap[model.BlogAttachmentRelationshipColumns.AttachmentThumbnail] = map[string][]any{
				"equalTo": []any{1},
			}
			mediaList, _, err := l.svcCtx.BlogPost.GetMedia(l.ctx, model.M{
				"orderBy": model.BlogAttachmentRelationshipColumns.AttachmentOrder,
				"select":  strings.Join(subSelectCols, ","),
			}, -1, mediaFilterMap)
			if err != nil {
				return nil, err
			}
			if len(mediaList) > 0 {
				for _, mediaItem := range mediaList {
					var url string
					url = mediaItem.AttachmentImageURL
					media = append(media, &blog.BlogMedia{
						Uid:       int64(mediaItem.AttachmentRelationshipID),
						Id:        int64(mediaItem.AttachmentID),
						Uri:       mediaItem.AttachmentSource,
						Thumbnail: int32(mediaItem.AttachmentThumbnail),
						Order:     int32(mediaItem.AttachmentOrder),
						Url:       url,
						AltText:   mediaItem.AttachmentImageAlt,
						Meta:      mediaItem.AttachmentImageMeta,
					})
				}
			}
		}
	}

	blogPostMetaRpcEntityName := model.RpcEntityNames.BlogPostMeta
	if rpcEntitySettingMap, hasRpcEntitySettingMap := subRpcEntitySettingMap[blogPostMetaRpcEntityName]; hasRpcEntitySettingMap {
		if preloadFields, hasPreloadFields := preloadMap[blogPostMetaRpcEntityName]; hasPreloadFields {
			var metaKeys []any
			for _, field := range preloadFields {
				fieldSetting, hasFieldSetting := rpcEntitySettingMap[field]
				if hasFieldSetting && fieldSetting.Name != "" {
					metaKeys = append(metaKeys, fieldSetting.Name)
				}
			}
			if len(metaKeys) > 0 {
				metaFilterMap := make(map[string]map[string][]any)
				metaFilterMap[model.BlogPostMetumColumns.PostID] = map[string][]any{
					"equalTo": []any{pid},
				}
				metaFilterMap[model.BlogPostMetumColumns.MetaKey] = map[string][]any{
					"in": metaKeys,
				}
				metaList, _, err := l.svcCtx.BlogPost.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
				if err != nil {
					return nil, err
				}
				if len(metaList) > 0 {
					for _, metum := range metaList {
						meta = append(meta, &blog.BlogMeta{
							Id:    int64(metum.MetaID),
							Key:   metum.MetaKey,
							Value: metum.MetaValue.String,
						})
					}
				}
			}
		}
	}

	var categories []*blog.BlogCategory
	var tags []*blog.BlogTag
	blogTermRpcEntityName := model.RpcEntityNames.BlogTerm
	blogTermRepositoryName := model.RepositoryNames.BlogTerm
	if _, hasRpcEntitySettingMap := subRpcEntitySettingMap[blogTermRpcEntityName]; hasRpcEntitySettingMap {
		preloadFields, hasPreloadFields := preloadMap[blogTermRpcEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogTermRepositoryName]
		if hasPreloadFields && hasSubColumnMap {
			subFilterMap := make(map[string]map[string][]any)
			subFilterMap[model.BlogTermRelationshipColumns.ObjectID] = map[string][]any{
				"equalTo": []any{pid},
			}
			subFilterMap[model.BlogTermRelationshipColumns.ObjectType] = map[string][]any{
				"equalTo": []any{enumx.PostTypePost},
			}
			relationshipList, _, err := l.svcCtx.BlogTerm.GetRelationshipList(l.ctx, model.M{
				"select": model.BlogTermRelationshipColumns.TermID,
			}, -1, subFilterMap)
			if err != nil {
				return nil, err
			}
			if len(relationshipList) > 0 {
				selectColMap := make(map[string]string)
				for _, field := range preloadFields {
					if _, exist := selectColMap[field]; !exist {
						if column, hasColumn := subColumnMap[field]; hasColumn {
							selectColMap[field] = column
						} else {
							selectColMap[field] = ""
						}
					}
				}
				var subSelectCols []string
				for _, column := range selectColMap {
					if column != "" {
						subSelectCols = append(subSelectCols, column)
					}
				}

				var tids []any // []model.BlogTerm.TermID
				for _, relationship := range relationshipList {
					tids = append(tids, relationship.TermID)
				}

				termFilterMap := make(map[string]map[string][]any)
				termFilterMap[model.BlogTermColumns.TermID] = map[string][]any{
					"in": tids,
				}
				termList, _, err := l.svcCtx.BlogTerm.GetList(l.ctx, model.M{
					"select": strings.Join(subSelectCols, ","),
				}, -1, termFilterMap)
				if err != nil {
					return nil, err
				}
				if len(termList) > 0 {
					for _, term := range termList {
						if term.Taxonomy == uint16(enumx.TermTaxonomyCategory) { // 是分类
							categories = append(categories, &blog.BlogCategory{
								Id:   int64(term.TermID),
								Name: term.Name,
								Slug: term.Slug,
							})
						} else if term.Taxonomy == uint16(enumx.TermTaxonomyTag) { // 是标签
							tags = append(tags, &blog.BlogTag{
								Id:   int64(term.TermID),
								Name: term.Name,
								Slug: term.Slug,
							})
						}
					}
				}
			}
		}
	}

	uri := post.PostDateGMT.Format("2006/01/02/") + post.PostName
	return &blog.PostDetailResponse{
		Id:            int64(post.ID),
		AuthorId:      int64(post.PostAuthorID),
		ParentId:      int64(post.PostParentID),
		Title:         post.PostTitle,
		Excerpt:       post.PostExcerpt,
		Status:        int32(post.PostStatus),
		CommentStatus: int32(post.CommentStatus),
		Slug:          post.PostName,
		Uri:           uri,
		Link:          post.GUID,
		Date:          modelx.FormatTime(post.PostDate, ""),
		DateGmt:       modelx.FormatTime(post.PostDateGMT, ""),
		Modified:      modelx.FormatTime(post.PostModifiedDate, ""),
		ModifiedGmt:   modelx.FormatTime(post.PostModifiedGMT, ""),
		CommentCount:  int32(post.CommentCount),
		ContentHtml:   contentHtml,
		Categories:    categories,
		Tags:          tags,
		Media:         media,
		Meta:          meta,
	}, nil

	// 	logx.Infof("PreloadFields : %+v ", in.PreloadField)

	// 	var q sq.SelectBuilder
	// 	q = l.svcCtx.BlogPostModel.RowBuilder("", "")

	// 	if in.PostType > 0 {
	// 		q = q.Where(sq.Eq{"post_type": in.PostType})
	// 	}
	// 	if in.PostStatus > 0 {
	// 		q = q.Where(sq.Eq{"post_status": in.PostStatus})
	// 	}

	// 	if in.Value != "" {
	// 		if in.Field != "" {
	// 			q = q.Where(sq.Eq{in.Field: in.Value})
	// 		} else {
	// 			q = q.Where(sq.Eq{"ID": in.Field})
	// 		}
	// 	}

	// 	q = q.Limit(1)
	// 	postList, err := l.svcCtx.BlogPostModel.QueryList(l.ctx, q)
	// 	if err != nil || len(postList) == 0 {
	// 		return nil, err
	// 	}
	// 	post := postList[0]

	// 	q = l.svcCtx.BlogPostDetailModel.RowBuilder("", "")
	// 	q = q.Where(sq.Eq{"post_id": string(post.ID)}).Limit(1)
	// 	postDetailList, err := l.svcCtx.BlogPostDetailModel.QueryList(l.ctx, q)
	// 	if err != nil {
	// 		return nil, err
	// 	}
	// 	var content string
	// 	if len(postDetailList) > 0 {
	// 		content = postDetailList[0].PostContent
	// 	}

	// 	q = l.svcCtx.BlogPostMetaModel.RowBuilder("", "")
	// 	q = q.Where(sq.Eq{"post_id": string(post.ID)})
	// 	postMetaList, err := l.svcCtx.BlogPostMetaModel.QueryList(l.ctx, q)
	// 	if err != nil {
	// 		return nil, err
	// 	}
	// 	var metaList []*blog.BlogMeta
	// 	if len(postMetaList) > 0 {
	// 		for _, meta := range postMetaList {
	// 			metaList = append(metaList, &blog.BlogMeta{
	// 				Id:    meta.PostMetaId,
	// 				Key:   meta.MetaKey,
	// 				Value: meta.MetaValue.String,
	// 			})
	// 		}
	// 	}

	// 	return &blog.PostDetailResponse{
	// 		Id:            post.ID,
	// 		Title:         post.PostTitle,
	// 		Excerpt:       post.PostExcerpt,
	// 		Status:        post.PostStatus,
	// 		CommentStatus: post.CommentStatus,
	// 		Slug:          post.PostName,
	// 		Uri:           post.Guid,
	// 		Content:       content,
	// 		Meta:          metaList,
	// 	}, nil

	// 	return nil, nil
}
